package com.tender.controller.templates;

import cn.hutool.json.JSONUtil;
import com.tender.dto.ShiroUserDTO;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.IncorrectCredentialsException;
import org.apache.shiro.authc.UnknownAccountException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import com.tender.common.Result;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.ResponseBody;
import com.tender.constants.Constants;
import com.tender.request.*;
import com.tender.service.JwtLoginService;

@Controller
public class ShiroLoginController {

    @Autowired
    private JwtLoginService jwtLoginService;

    /**
     * 访问 login.html 页面
     */
    @GetMapping("/login")
    public String login() {
        return "login";
    }

    /**
     * 登录逻辑处理
     */
    @PostMapping("/login")
    public String login(String username, String password, Model model) {
        /** 使用Shiro编写认证操作 */
        // 1.获取Subject
        Subject subject = SecurityUtils.getSubject();
        // 2.封装用户数据
        UsernamePasswordToken token = new UsernamePasswordToken(username, password);

        // 3.执行登录方法
        try {
            subject.login(token);
            // 登录成功
            // 跳转到 home.html
            return "redirect:home";
        } catch (UnknownAccountException e) {
            // 登录失败:用户名不存在
            System.out.println("用户名不存在");
            model.addAttribute("userNameNotExists", "用户名不存在");
            return "login";
        } catch (IncorrectCredentialsException e) {
            // 登录失败:密码错误
            System.out.println("密码错误");
            model.addAttribute("passwordNotCorrect", "密码错误");
            return "login";
        } catch (ExcessiveAttemptsException e) {
            // 登录失败:密码错误
            System.out.println("密码错误次数超过 " + (Constants.PASSWORD_TRY_LIMIT + 1) + " 次");
            model.addAttribute("passwordErrorNum", "密码失败次数超过 " + (Constants.PASSWORD_TRY_LIMIT + 1) + " 次，请多xxx 分钟后再尝试");
            return "login";
        }
    }

    /**
     * jwt 登录认证
     */
    @PostMapping("/login4jwt")
    @ResponseBody // 返回json 数据
    public Result<String> Login4Jwt(@RequestBody LoginRequest request) {
        String token = null;
        String code = null;
        String msg = null;
        try {
            token = jwtLoginService.jwtLogin(request);
        } catch (UnknownAccountException ex) {
            code = Constants.LOGIN_NAME_NOT_EXIST;
            msg = Constants.LOGIN_NAME_NOT_EXIST_MESSAGE;
        } catch (IncorrectCredentialsException ex) {
            code = Constants.PASSWORD_INCORRECT_CODE;
            msg = Constants.PASSWORD_INCORRECT_MESSAGE;
        } catch (ExcessiveAttemptsException ex) {
            code = Constants.PASSWORD_ATTEMPTS_EXCEEDED_CODE;
            msg = Constants.PASSWORD_ATTEMPTS_EXCEEDED_MESSAGE;
        }

        Result<String> result = Result.of(token);
        result.setResultCode(code);
        result.setResultMsg(msg);

        return result;
    }

    @GetMapping("/logout")
    public String logout() {
        // 1.获取Subject
        Subject subject = SecurityUtils.getSubject();
        if (null != subject) {
            // 2.退出
            subject.logout();
        }

        return "login";
    }

    @GetMapping("/unauthorized")
    public String unauthorized() {
        return "unauthorized";
    }

    /**
     * 添加页面跳转
     */
    //需要user:add权限才能访问
    @RequiresPermissions("user:add")
    @GetMapping("/add")
    public String add() {
        return "add";
    }

    /**
     * 修改页面跳转
     */
    //需要user:update权限才能访问
    @RequiresPermissions("user:update")
    @GetMapping("/update")
    public String update() {
        return "update";
    }

    @GetMapping("/get/user")
    @ResponseBody // 返回json格式字符串给浏览器
    public Result<ShiroUserDTO> getUserInfo() {
        ShiroUserDTO shiroUserDTO = JSONUtil.toBean(JSONUtil.toJsonStr(SecurityUtils.getSubject().getPrincipal()), ShiroUserDTO.class);

        return Result.of(shiroUserDTO);
    }
}
